package com.smartcommunity.service.village.impl;

import cn.hutool.core.util.NumberUtil;
import com.smartcommunity.base.common.CacheMap;
import com.smartcommunity.bean.constant.Constant;
import com.smartcommunity.bean.enumeration.ResultCode;
import com.smartcommunity.bean.enumeration.SymbolEnum;
import com.smartcommunity.bean.model.Result;
import com.smartcommunity.dao.people.PeopleDao;
import com.smartcommunity.dao.sixEntity.SixEntityDao;
import com.smartcommunity.dao.village.HouseDao;
import com.smartcommunity.dao.village.VillageDao;
import com.smartcommunity.elasticsearch.house.HouseEsApi;
import com.smartcommunity.entity.house.HouseListFloorResp;
import com.smartcommunity.entity.house.HouseListHouseResp;
import com.smartcommunity.entity.house.HouseListUnitResp;
import com.smartcommunity.entity.people.People;
import com.smartcommunity.entity.sixEnity.DataTypeStatistic;
import com.smartcommunity.entity.statistic.StatisticByTypeResp;
import com.smartcommunity.entity.village.Building;
import com.smartcommunity.entity.village.House;
import com.smartcommunity.entity.village.HouseListReq;
import com.smartcommunity.entity.village.SixStatisticsEntity;
import com.smartcommunity.entity.village.dto.HouseTypeEditBatch;
import com.smartcommunity.es.common.EsBasedataEnum;
import com.smartcommunity.exception.BusinessException;
import com.smartcommunity.utils.StringUtils;
import com.smartcommunity.dao.building.UnitMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.smartcommunity.entity.building.UnitEntity;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @version V2.1
 * @ClassName: HouseService
 * @Description: 房屋处理
 * @author: minsheng
 * @Date: 2019/3/4 9:38
 * @Company:
 */
@Service
@Slf4j
public class HouseService {
    /***********************实有房屋处理********************************************/

    @Autowired
    private HouseDao dao;
    @Autowired
    private PeopleDao peopleDao;

    @Autowired
    private VillageDao villageDao;

    @Autowired
    private UnitMapper unitMapper;

    @Autowired
    private SixEntityDao sixEntityDao;

    @Autowired
    private HouseEsApi houseEsApi;


    public int getHouseCount() {
        return dao.getHouseCount();
    }

    /**
     * 删除房屋
     *
     * @param ids
     * @return
     */
    @Transactional(value = "mysqlTransactionManager", rollbackFor = {BusinessException.class})
    public Result deleteHouse(String ids) {
        StringBuffer msg = new StringBuffer();
        //转换id数组，支持批量删除
        String[] array = ids.split(SymbolEnum.COMMA.toString());
        List<House> list = new ArrayList<House>(array.length);
        for (String arr : array) {
            int id = Integer.parseInt(arr);
            //根据id列表获取房屋信息
            House hou = dao.getHouseById(id);
            //校验房屋下是否有人员信息
            if (dao.checkHousePeople(hou) > 0) {
                msg.append(hou.getHouseNo()).append(",");
                continue;
            }
            hou.setId(Integer.parseInt(arr));
            list.add(hou);
        }

        //提示删除失败的楼栋信息
        if (msg.length() > 0) {
            return Result.error(ResultCode.HOUSE_PEOPLE_EXSIT_DELETE.code(),
                    String.format(ResultCode.HOUSE_PEOPLE_EXSIT_DELETE.msg(), msg.substring(0, msg.length() - 1)));
        }

        if (list.size() > 0) {
            dao.deleteHouse(list);
            houseEsApi.batchDelete(Arrays.asList(array));
        }
        return Result.ok();
    }

    /**
     * @Description: 更新房屋
     * @param: [list]
     * @return: int
     * @auther: minsheng
     * @date: 2019/3/5 14:00
     */
    @Transactional(value = "mysqlTransactionManager", rollbackFor = {BusinessException.class})
    public Result updateHouse(House ho) {
        House house = dao.getHouseById(ho.getId());
        if (house == null) {
            return Result.error(ResultCode.HOUSE_NOT_EXSIT);
        }
        //补全房屋的小区编码
        if (StringUtils.isEmpty(ho.getVillageCode())) {
            ho.setVillageCode(house.getVillageCode());
        }
        List<House> list = new ArrayList<>();
        list.add(ho);
        //校验所更新的房屋信息是否存在
        if (dao.updateCheckHouse(ho) != null) {
            return Result.error(ResultCode.HOUSE_UPDATE_EXSIT);
        }

        dao.updateHouse(list);
        houseEsApi.saveOrUpdate(ho);
        return Result.ok();
    }

    /**
     * @Description: 新增房屋
     * @param: [list]
     * @return: java.util.List
     * @auther: minsheng
     * @date: 2019/3/5 14:01
     */
    @Transactional(value = "mysqlTransactionManager", rollbackFor = {BusinessException.class})
    public Result addHouse(House house) {
        Map<String, String> map = new HashMap<>();
        map.put("villageCode", house.getVillageCode());
        map.put("buildingNo", house.getBuildingNo());
        map.put("houseNo", house.getHouseNo());
        Building building = new Building();
        building.setVillageCode(house.getVillageCode());
        building.setBuildingNo(house.getBuildingNo());
        building = villageDao.getBuilding(building);
        if (StringUtils.isNotEmpty(house.getFloor())) {
            if (!NumberUtil.isNumber(house.getFloor())) {
                return Result.error(ResultCode.BAD_REQUEST_PARAM_ERROR.code(), "请输入正确的楼层信息!");
            } else {
                if (Integer.parseInt(house.getFloor()) > building.getFloorTotal()) {
                    return Result.error(ResultCode.HOUSE_MAX_FLOOR.code(),
                            String.format(ResultCode.HOUSE_MAX_FLOOR.msg(), building.getFloorTotal()));
                }
            }
        }

        House hou = dao.checkHouse(map);
        if (hou != null) {
            return Result.error(ResultCode.HOUSE_EXSIT);
        }
        List<House> list = new ArrayList<>();
        list.add(house);
        dao.addHouse(list);
        houseEsApi.saveOrUpdate(house);
        return Result.ok();
    }

    /**
     * @Description: 查询房屋信息
     * @param: [list]
     * @return: java.util.List
     * @auther: minsheng
     * @date: 2019/3/5 14:01
     */
    public List getHouse(List list) {
        return dao.getHouse(list);
    }

    /**
     * 房屋-数据迁移到ES-basedata索引
     */
    public Result syncDataToEs() throws Exception {
        int totalCount = villageDao.getAllHouseCountForEs();
        int pageSize = 10000;
        int totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
        for (int currentPage = 1; currentPage <= totalPage; currentPage++) {
            List<House> houseList = villageDao.listHousesForEs((currentPage - 1) * pageSize, pageSize);
            if (CollectionUtils.isNotEmpty(houseList)) {
                log.info("--------房屋-数据迁移到ES-basedata索引:第{}页,数据总量:{}--------", currentPage, houseList.size());
                houseEsApi.batchSaveOrUpdateHouse(houseList);
            }
        }
        return Result.ok();
    }


    /************************人房关系处理*********************************/
    /**
     * @Description: 删除人房关系
     * @param: [list]
     * @return: java.util.List
     * @auther: minsheng
     * @date: 2019/3/5 14:02
     */
    public Result deletePeopleHouse(List list) {
        list.forEach(map -> {
            dao.deletePeopleHouse((Map) map);
        });

        return Result.ok();
    }

    /**
     * @Description: 更新人房关系
     * @param: [list]
     * @return: java.util.List
     * @auther: minsheng
     * @date: 2019/3/5 14:02
     */
    public Result updatePeopleHouse(List list) {
        dao.updatePeopleHouse(list);
        return Result.ok();
    }

    /**
     * @Description: 新增人房关系
     * @param: [list]
     * @return: java.util.List
     * @auther: minsheng
     * @date: 2019/3/5 14:02
     */
    public Result insertPeopleHouse(List list) {
        dao.insertPeopleHouse(list);
        return Result.ok();
    }

    /**
     * @Description: 查询人房关系列表
     * @param: [param]
     * @return: java.util.List
     * @auther: minsheng
     * @date: 2019/3/5 14:03
     */
    public List<Map> listPeople(Map param) {
        List<Map> list = dao.listPeople(param);

        if (list != null) {
            list.stream().forEach(map -> CacheMap.HOUSE_NAME_MAP.forEach((k, v) -> {
                if (map.get("type") != null && map.get("type").equals(v)) {
                    map.put("type", k);
                }
            }));
        }
        return list;
    }

    public Result countHouseByType(Map<String, Object> paramMap) {
        //初始化数据
        Map<Integer, DataTypeStatistic> map = new HashMap<>();
        for (Map.Entry<Integer, String> entry : CacheMap.HOUSE_TYPE_MAP.entrySet()) {
            //类型值
            Integer value = Integer.parseInt(entry.getKey() + "");
            //页面设计只显示下面四种类型
            if (Constant.HOUSESELF_VALUE == value || Constant.HOUSERENT_VALUE == value ||
                    Constant.HOUSEEMPTY_VALUE == value || Constant.HOUSEOTHER_VALUE == value) {
                DataTypeStatistic dataTypeStatistic = new DataTypeStatistic();
                //类型名称
                dataTypeStatistic.setName(entry.getValue());
                dataTypeStatistic.setValue(value);
                map.put(value, dataTypeStatistic);
            }
        }
        //获取房屋类型统计，从任务结果中获取
        List<SixStatisticsEntity> sixList = sixEntityDao.getCountByChildType(paramMap);
        for (SixStatisticsEntity six : sixList) {
            int type = six.getChildType();
            int count = six.getCount();
            DataTypeStatistic dataTypeStatistic = map.get(type);
            //除了这三类，剩余归到其他类
            if (Constant.HOUSESELF_VALUE == type || Constant.HOUSERENT_VALUE == type || Constant.HOUSEEMPTY_VALUE == type) {
                if (dataTypeStatistic == null) {
                    continue;
                }
                dataTypeStatistic.setNum(count);
            } else {
                DataTypeStatistic other = map.get(Constant.HOUSEOTHER_VALUE);
                other.setNum(other != null ? other.getNum() + count : 0);
            }
        }
        List<DataTypeStatistic> list = new ArrayList<>();
        for (Integer key : map.keySet()) {
            list.add(map.get(key));
        }

        //根据value排序显示
        Collections.sort(list, new Comparator<DataTypeStatistic>() {
            public int compare(DataTypeStatistic o1, DataTypeStatistic o2) {
                return o1.getValue() - o2.getValue();
            }
        });

        return Result.ok(list);
    }

    /**
     * 删除人房关系
     *
     * @param credentialNo
     */
    public void deleteRelPeopleHouse(String credentialNo) {
        dao.deleteRelPeopleHouse(credentialNo);
    }

    public List<StatisticByTypeResp> getHouseTypeCount() {
        List<StatisticByTypeResp> houseTypeCount = dao.getHouseTypeCount();
        if (CollectionUtils.isNotEmpty(houseTypeCount)) {
            houseTypeCount.forEach(statisticByType -> {
                statisticByType.setTypeName(CacheMap.HOUSE_TYPE_MAP.get(statisticByType.getType()));
            });
        }
        return houseTypeCount;
    }

    public List<HouseListUnitResp> list(HouseListReq houseListReq) {
        //根据辖区查询实有人口信息
        List<People> peoples = peopleDao.queryPeopleByVillageCode(houseListReq.getVillageCode(), houseListReq.getBuildingNo(), houseListReq.getUnitNo());
        Map<String, Set<String>> peopleCountsMap = new HashMap<>();
        peoples.forEach(people -> {
            String key = people.getVillageCode() + ":" + people.getBuildingNo() + ":" + people.getUnitNo() + ":" + people.getHouseNo();
            if (peopleCountsMap.containsKey(key)) {
                Set<String> credentialNoS = peopleCountsMap.get(key);
                credentialNoS.add(people.getCredentialNo());
                peopleCountsMap.put(key, credentialNoS);
            } else {
                Set<String> credentialNoS = new HashSet<>();
                credentialNoS.add(people.getCredentialNo());
                peopleCountsMap.put(key, credentialNoS);
            }
        });
        //查询小区房屋信息
        List<House> houses = dao.queryHouseByVillageCode(houseListReq.getVillageCode(), houseListReq.getBuildingNo(), houseListReq.getUnitNo());
        List<HouseListHouseResp> houseListResps = houses.stream().map(house -> {
            HouseListHouseResp houseListHouseResp = new HouseListHouseResp();
            houseListHouseResp.setRealPeopleCounts(0l);
            BeanUtils.copyProperties(house, houseListHouseResp);
            String key = house.getVillageCode() + ":" + house.getBuildingNo() + ":" + house.getUnitNo() + ":" + house.getHouseNo();
            if (peopleCountsMap.containsKey(key)) {
                houseListHouseResp.setRealPeopleCounts((long) peopleCountsMap.get(key).size());
            }
            return houseListHouseResp;
        }).collect(Collectors.toList());
        List<HouseListUnitResp> unitResps = new ArrayList<>();

        //根据条件查询房屋信息
//        List<HouseListHouseResp> houseListResps = dao.list(houseListReq);
        //查询楼栋单元信息
        List<UnitEntity> unitEntities = unitMapper.queryBuildingUnit(houseListReq.getVillageCode(), houseListReq.getBuildingNo());
        Map<String, UnitEntity> unitMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(unitEntities)) {
            unitEntities.forEach(unitEntity -> {
                unitMap.put(unitEntity.getUnitNo(), unitEntity);
            });
        }

        if (!CollectionUtils.isEmpty(houseListResps)) {
            //房屋信息根据单元编号分组
            Map<String, List<HouseListHouseResp>> unitHouseMap = houseListResps.stream().collect(Collectors.groupingBy(HouseListHouseResp::getUnitNo));

            unitHouseMap.forEach((unitNo, houseListHouseResps) -> {
                //将每单元的房屋，根据楼层分组
                Map<String, List<HouseListHouseResp>> floorHouseMap = houseListHouseResps.stream().collect(Collectors.groupingBy(HouseListHouseResp::getFloor));

                List<HouseListFloorResp> floors = new ArrayList<>();
                floorHouseMap.forEach((floorNo, floorHouses) -> {
                    //对楼层中的房屋信息排序并 补全房屋类型说明
                    floorHouses = floorHouses.stream().sorted(Comparator.comparing(HouseListHouseResp::getHouseNo)).map(houseListHouseResp -> {
                        houseListHouseResp.setTypeDesc();
                        return houseListHouseResp;
                    }).collect(Collectors.toList());
                    //封装楼层返回信息实体
                    HouseListFloorResp houseListFloorResp = new HouseListFloorResp();
                    houseListFloorResp.setFloorNo(floorNo);
                    houseListFloorResp.setHouses(floorHouses);
                    floors.add(houseListFloorResp);
                });
                //对楼层排序 封装单元返回实体
                Collections.sort(floors, (o1, o2) -> {
                    int floor1 = 0;
                    int floor2 = 0;
                    try {
                        floor1 = Integer.parseInt(o1.getFloorNo());
                        floor2 = Integer.parseInt(o2.getFloorNo());
                    } catch (NumberFormatException e) {
                        log.error("楼层转换为数字失败,floor1:{},floor2:{},e:", o1.getFloorNo(), o2.getFloorNo(), e);
                    }
                    return floor1 - floor2;
                });

                HouseListUnitResp unitResp = new HouseListUnitResp();
                unitResp.setUnitNo(unitNo);
                unitResp.setFloors(floors);
                unitResp.setUnitOrder(0);
                if (unitMap.containsKey(unitNo)) {
                    UnitEntity unitEntity = unitMap.get(unitNo);
                    if (null != unitEntity.getUnitOrder()) {
                        unitResp.setUnitOrder(unitEntity.getUnitOrder());
                    }
                }
                unitResps.add(unitResp);
            });
        }
        unitResps.sort(Comparator.comparing(HouseListUnitResp::getUnitOrder));
        return unitResps;
    }

    public void houseTypeEditBatch(HouseTypeEditBatch houseTypeEditBatch) {
        //更新数据库
        dao.houseTypeEditBatch(houseTypeEditBatch);
        //更新ES
        Map<String, Map<String, Object>> esUpdateMap = new HashMap<String, Map<String, Object>>();
        Map<String, Object> valueMap = new HashMap<>();
        valueMap.put("houseType", houseTypeEditBatch.getType());
        for (Integer houseId : houseTypeEditBatch.getHouseIds()) {
            if (houseId != null) {
                esUpdateMap.put(houseId + Constant.SEPARATOR + EsBasedataEnum.HOUSE.getIntValue(), valueMap);
            }
        }
        try {
            if (!org.springframework.util.CollectionUtils.isEmpty(esUpdateMap)) {
                houseEsApi.batchUpdate(esUpdateMap);
            }
        } catch (Exception e) {
            log.error("批量修改房屋类型入库ES失败, e");
        }
    }
}
